package top.usts.springframework.beans.factory;

import top.usts.springframework.beans.BeansException;
import top.usts.springframework.beans.PropertyValue;
import top.usts.springframework.beans.PropertyValues;
import top.usts.springframework.beans.factory.config.BeanDefinition;
import top.usts.springframework.beans.factory.config.BeanFactoryPostProcessor;
import top.usts.springframework.core.io.DefaultResourceLoader;
import top.usts.springframework.core.io.Resource;
import top.usts.springframework.util.StringValueResolver;

import java.util.Properties;

/**
 * @description:
 *
 * Placeholder 占位符
 * @author: CJ
 * @date: 2022/2/26
 */
public class PropertyPlaceholderConfigurer implements BeanFactoryPostProcessor {

    /**
     * Default placeholder  prefix  占位符前缀
     */
    public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";

    /**
     * 占位符后缀
     */
    public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";

    private  String location;

    @Override
    public void postProcessBeanFactory(ConfigureableListableBeanFactory beanFactory) {
        //加载属性配置文件
        try {
            DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
            Resource resource = resourceLoader.getResource(location);

            //暂未付替换属性
            Properties properties = new Properties();
            properties.load(resource.getInputStream());

            String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
            for (String beanName : beanDefinitionNames) {
                BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);

                PropertyValues propertyValues = beanDefinition.getPropertyValues();
                for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
                    Object value = propertyValue.getValue();
                    if(!(value instanceof String)) continue;

                    value = resolvePlaceholder((String) value, properties);
                    propertyValues.addPropertyValue(new PropertyValue(propertyValue.getName(), value));
                }

                //向容器中添加字符串解析器，供解析@Value注解使用
                PlaceHolderResolvingStringValueResolver valueResolver = new PlaceHolderResolvingStringValueResolver(properties);
                beanFactory.addEmbeddedValueResolver(valueResolver);

            }
        } catch (Exception e) {
            throw new BeansException("Could not load properties", e);
        }
    }

    private String resolvePlaceholder(String value, Properties properties) {
        String strVal = value;
        StringBuilder buffer = new StringBuilder(strVal);
        int startIdx = strVal.indexOf(DEFAULT_PLACEHOLDER_PREFIX);
        int stopIdx = strVal.indexOf(DEFAULT_PLACEHOLDER_SUFFIX);
        if (startIdx != -1 && stopIdx != -1 && startIdx < stopIdx) {
            String propKey = strVal.substring(startIdx + 2, stopIdx);
            String propVal= properties.getProperty(propKey);
            buffer.replace(startIdx, stopIdx + 1, propVal);
        }
        return buffer.toString();
    }

    private class PlaceHolderResolvingStringValueResolver implements StringValueResolver {
        private final Properties properties;

        public PlaceHolderResolvingStringValueResolver(Properties properties) {
            this.properties = properties;
        }

        @Override
        public String resolveStringValue(String strVal) {
            return PropertyPlaceholderConfigurer.this.resolvePlaceholder(strVal, properties);
        }
    }


    public void setLocation(String location) {
        this.location = location;
    }
}
